﻿using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WeatherHistory.Api.CommandsQueries.Commands.Regions.AttachWeather;
using WeatherHistory.Api.CommandsQueries.Commands.Regions.Create;
using WeatherHistory.Api.CommandsQueries.Commands.Regions.Delete;
using WeatherHistory.Api.CommandsQueries.Commands.Regions.DetachWeather;
using WeatherHistory.Api.CommandsQueries.Commands.Regions.Update;
using WeatherHistory.Api.CommandsQueries.Queries.Regions.GetOne;
using WeatherHistory.Api.CommandsQueries.Queries.Regions.Search;
using WeatherHistory.Api.Filters;
using WeatherHistory.Shared.Constants;
using WeatherHistory.Shared.Validation;

namespace WeatherHistory.Api.Controllers;

/// <summary>
///     Контроллер для работы с регионами
/// </summary>
[ServiceFilter(typeof(AuthFilter))]
[Route("region")]
public class RegionController : ApiControllerBase
{
    /// <summary>Создание региона</summary>
    [HttpPost]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(typeof(CreateRegionsCommandResponse), StatusCodes.Status201Created)]
    public async Task<ActionResult<CreateRegionsCommandResponse>> Create([FromBody] CreateRegionsCommandRequest request)
    {
        request.CreatorId = long.Parse(HttpContext.Request.Cookies["id"]!);
        var result = await Mediator.Send(request);
        return Created($"/region/{result.Id}", result);
    }

    /// <summary>Получение информации о регионе</summary>
    [HttpGet("{regionId:long}")]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(typeof(CreateRegionsCommandResponse), StatusCodes.Status200OK)]
    public async Task<ActionResult<CreateRegionsCommandResponse>> GetOne([FromRoute] [GreaterThan(0L)] long regionId)
    {
        var request = new GetOneRegionsQueryRequest();
        request.RegionId = regionId;

        var result = await Mediator.Send(request);
        return Ok(result);
    }
    
    /// <summary>Поиск регионов</summary>
    [HttpGet("search")]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(typeof(SearchRegionsQueryResponse), StatusCodes.Status200OK)]
    public async Task<ActionResult<SearchRegionsQueryResponse>> Search([FromQuery] SearchRegionsQueryRequest request)
    {
        var result = await Mediator.Send(request);
        return Ok(result);
    }

    /// <summary>Удаление региона</summary>
    [HttpDelete("{regionId:long}")]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult> Delete([FromRoute] [GreaterThan(0L)] long regionId)
    {
        var request = new DeleteRegionsCommandRequest();
        request.RegionId = regionId;

        await Mediator.Send(request);
        return Ok();
    }

    /// <summary>Обновление региона</summary>
    [HttpPut("{regionId:long}")]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(UpdateRegionsCommandResponse), StatusCodes.Status200OK)]
    public async Task<ActionResult<UpdateRegionsCommandResponse>> Update([FromBody] UpdateRegionsCommandRequest request, [FromRoute] [GreaterThan(0L)] long regionId)
    {
        request.RegionId = regionId;
        var result = await Mediator.Send(request);
        return Ok(result);
    }

    /// <summary>Добавление к региону записи о погоде</summary>
    [HttpPost("{regionId:long}/weather/{weatherId:long}")]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(typeof(AttachWeatherRegionsCommandResponse), StatusCodes.Status200OK)]
    public async Task<ActionResult<AttachWeatherRegionsCommandResponse>> AttachWeather([FromRoute] [GreaterThan(0L)] long regionId, [FromRoute] [GreaterThan(0L)] long weatherId)
    {
        var request = new AttachWeatherRegionsCommandRequest();
        request.RegionId = regionId;
        request.WeatherId = weatherId;

        var result = await Mediator.Send(request);
        return Ok(result);
    }

    /// <summary>Удаление из региона записи о погоде</summary>
    [HttpDelete("{regionId:long}/weather/{weatherId:long}")]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(typeof(DetachWeatherRegionsCommandResponse), StatusCodes.Status200OK)]
    public async Task<ActionResult<DetachWeatherRegionsCommandResponse>> DetachWeather([FromRoute] [GreaterThan(0L)] long regionId, [FromRoute] [GreaterThan(0L)] long weatherId)
    {
        var request = new DetachWeatherRegionsCommandRequest();
        request.RegionId = regionId;
        request.WeatherId = weatherId;

        var result = await Mediator.Send(request);
        return Ok(result);
    }
}